package com.pt25.base.util;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.concurrent.*;

/**
 * 线程池工具类
 */
public class ExecutorUtil {

    /**
     * 在 ThreadPoolTaskExecutor 中，setRejectedExecutionHandler 方法用于设置线程池的任务拒绝策略。当线程池的工作队列已满且所有线程都在忙碌时，新提交的任务将根据指定的拒绝策略进行处理。Java 提供了四种内置的拒绝策略实现，全部位于 java.util.concurrent 包中：
     * <p>
     * 1. AbortPolicy（默认策略）
     * 实现类：ThreadPoolExecutor.AbortPolicy
     * 行为：直接抛出 RejectedExecutionException 异常
     * 适用场景：需要严格保证任务不被丢失的场景
     * 示例：
     * <p>
     * java
     * executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
     * 2. CallerRunsPolicy
     * 实现类：ThreadPoolExecutor.CallerRunsPolicy
     * 行为：将任务回退给提交任务的线程执行（调用者自己运行任务）
     * 特点：
     * <p>
     * 会降低新任务提交速度
     * <p>
     * 实际相当于将线程池的并行处理退化为串行
     * 适用场景：不允许任务丢失且可以接受短暂性能下降的场景
     * 示例：
     * <p>
     * java
     * executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
     * 3. DiscardPolicy
     * 实现类：ThreadPoolExecutor.DiscardPolicy
     * 行为：静默丢弃新提交的任务，不做任何通知
     * 风险：可能导致业务逻辑中断且无感知
     * 适用场景：允许丢弃非关键任务的场景（如日志记录）
     * 示例：
     * <p>
     * java
     * executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
     * 4. DiscardOldestPolicy
     * 实现类：ThreadPoolExecutor.DiscardOldestPolicy
     * 行为：丢弃队列中最旧的任务（队头的任务），然后尝试重新提交新任务
     * 风险：可能丢失重要历史任务
     * 适用场景：允许丢弃旧任务的实时流处理场景
     * 示例：
     * <p>
     * java
     * executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
     * 5. 自定义拒绝策略（高级用法）
     * 通过实现 RejectedExecutionHandler 接口创建自定义策略：
     * <p>
     * java
     * public class CustomRejectionHandler implements RejectedExecutionHandler {
     *
     * @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
     * // 自定义逻辑（如记录日志、存入数据库、降级处理等）
     * logger.warn("Task rejected: {}", r.toString());
     * // 尝试重新放入队列
     * if (!executor.isShutdown()) {
     * executor.getQueue().put(r);
     * }
     * }
     * }
     * <p>
     * // 使用方式
     * executor.setRejectedExecutionHandler(new CustomRejectionHandler());
     * 各策略对比
     * 策略	              是否抛异常	数据丢失风险	系统影响	         适用场景
     * AbortPolicy	        是	       无	       可能中断流程	严格不允许丢失任务
     * CallerRunsPolicy	    否	       无	       降低提交速度	一般业务场景（推荐）
     * DiscardPolicy	    否	       高	       无感知丢失	     非关键任务
     * DiscardOldestPolicy	否	      中等	        丢失旧任务	实时数据处理
     * 自定义策略	          可控制	     可控制	      灵活	         特殊需求
     */

    private static final ConcurrentHashMap<String, ExecutorService> executorServiceMap = new ConcurrentHashMap<>();

    public static ExecutorService getExecutor(ExecutorConfig executorConfig) {
        ExecutorService executorService = executorServiceMap.get(executorConfig.getExecutorName());
        if (executorService == null) {
            synchronized (executorServiceMap) {
                executorService = executorServiceMap.get(executorConfig.getExecutorName());
                if (executorService == null) {
                    int recommendedThreadPoolSize = SystemInfoUtil.getRecommendedThreadPoolSize();
                    executorConfig.setCorePoolSize(null == executorConfig.getCorePoolSize() ? recommendedThreadPoolSize : executorConfig.getCorePoolSize());
                    executorConfig.setMaximumPoolSize(null == executorConfig.getMaximumPoolSize() ? recommendedThreadPoolSize : executorConfig.getMaximumPoolSize());
                    executorService = new ThreadPoolExecutor(
                            executorConfig.getCorePoolSize(),
                            executorConfig.getMaximumPoolSize(),
                            executorConfig.getKeepAliveTime(),
                            TimeUnit.MINUTES,
                            new LinkedBlockingDeque<>(executorConfig.capacity),
                            Executors.defaultThreadFactory(),
                            RejectionCategory.getRejectedExecutionHandler(executorConfig.getRejectionCategory())
                    );
                    executorServiceMap.put(executorConfig.getExecutorName(), executorService);
                }
            }
        }
        return executorService;
    }

    public static ExecutorService getExecutor(String executorName) {
        ExecutorService executorService = executorServiceMap.get(executorName);
        if (executorService == null) {
            executorService = getExecutor(ExecutorConfig.builder().executorName(executorName).build());
        }
        return executorService;
    }


    /**
     * 创建线程的配置类
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class ExecutorConfig {
        /**
         * 线程线程池的名称
         */
        private String executorName;
        /**
         * 线程池的任务拒绝策略
         */
        @Builder.Default
        private RejectionCategory rejectionCategory = RejectionCategory.CallerRunsPolicy;
        /**
         * 线程池最小线程数
         */
        private Integer corePoolSize;
        /**
         * 线程池最大线程数
         */
        private Integer maximumPoolSize;
        /**
         * 线程池线程空闲存活时长(单位：分钟)
         */
        @Builder.Default
        private Long keepAliveTime = 10L;
        /**
         * 等待队列大小
         */
        @Builder.Default
        private Integer capacity = 100;
    }

    /**
     * 线程池拒绝策略
     */
    public  enum RejectionCategory {
        AbortPolicy, CallerRunsPolicy, DiscardPolicy, DiscardOldestPolicy;

        public static RejectedExecutionHandler getRejectedExecutionHandler(RejectionCategory category) {
            return switch (category) {
                case AbortPolicy -> new ThreadPoolExecutor.AbortPolicy();
                case CallerRunsPolicy -> new ThreadPoolExecutor.CallerRunsPolicy();
                case DiscardPolicy -> new ThreadPoolExecutor.DiscardPolicy();
                case DiscardOldestPolicy -> new ThreadPoolExecutor.DiscardOldestPolicy();
            };
        }
    }
}
